#!/usr/bin/env python
# -*- coding:utf8 -*-
import scrapy
import copy
import math
import json
import ddddocr
import traceback
from scrapy import Request, FormRequest, cmdline
from runnerSpider.spiders.shuzixindong.password_encrypt import *


class shuzixindongSpider(scrapy.Spider):
    name = "shuzixindong"
    login_url = "https://api-changzheng.chinaath.com/changzheng-user-center-api/login"
    unbind_url = "https://api-changzheng.chinaath.com/changzheng-user-center-api/api/authentication/business/unBusinessAuthentication"
    bind_url = "https://api-changzheng.chinaath.com/changzheng-user-center-api/api/authentication/business"
    user_url = "https://api-changzheng.chinaath.com/changzheng-user-center-api/api/account/app/detail/get"
    score_url = "https://api-changzheng.chinaath.com/changzheng-common-proxy-api/api/score/proxy/queryMineOfflineRaceScore"
    race_url = "https://api-changzheng.chinaath.com/changzheng-race-proxy-api/api/race/zone/query/pageForApp"
    img_url = "https://api-changzheng.chinaath.com/changzheng-basic-center-api/api/imageVerify/getUniqueIdByBusinessType?imageVerifyBusinessType=5"
    yzm_url = "https://api-changzheng.chinaath.com/changzheng-basic-center-api/api/imageVerify/getVerifyCode?uniqueId={}"
    register_url = "https://api-changzheng.chinaath.com/changzheng-website-center-api/api/website/search/getAppBaseRegisterInfo"
    all_race_url = "https://api-changzheng.chinaath.com/changzheng-content-center-api/api/global/search/resultList"
    certificate_url = "https://api-changzheng.chinaath.com/changzheng-score-center-api/api/app/score/getCertificateStandardById?scoreId={}"
    header = {
        "machineCode": "6bd839d8b9f7f76d",
        "osId": "1002",
        "device": "pad/12 HUAWEI MGA-AL00",
        "versionNumber": "519",
        "versionCode": "5.54.0",
        "terminalType": "1",
        "Content-Type": "application/x-www-form-urlencoded",
        "Host": "api-changzheng.chinaath.com",
    }

    def start_requests(self):
        try:
            self.logger.info("开始登录")
            password = encrypt_password("aa123456")
            login_data = {"loginType": "0", "password": password, "phone": "13981808836", "encryptType": "1"}
            yield FormRequest(url=self.login_url, formdata=login_data, callback=self.parse,
                              headers=self.header, dont_filter=True)
        except Exception:
            self.logger.error(f"登录时出错：{traceback.format_exc()}")

    def parse(self, response, **kwargs):
        try:
            data = json.loads(response.text)
            token = data.get("data", {}).get("token", "")
            card_number = data.get("data", {}).get("userInfo", {}).get("cardNumber", "")
            header = copy.deepcopy(self.header)
            header.update({"token": token, "Content-Type": "application/json; charset=UTF-8"})
            if card_number:
                #可查询成绩的赛事
                # data = {"raceCategoryCodeList": ["race_type_offline"], "searchType": "1", "pageNo": "1", "pageSize": "1000",
                #         "keyword": ""}
                # yield Request(url=self.all_race_url, callback=self.all_race_parse, method="POST", headers=header,
                #               body=json.dumps(data), dont_filter=True, meta={"header": header})


                yield Request(url=self.unbind_url, callback=self.unbind_parse, method="POST", headers=header,
                              body=json.dumps({"cardNumber": card_number}), dont_filter=True, meta={"header": header})
            else:
                # bind_data = {"authType": 1,
                #              "realNameAuthenticationInfo": {"cardNumber": "511321198612302823", "cardType": 0,
                #                                             "userName": "杜璐"}}
                bind_data = {"authType": 1,
                             "realNameAuthenticationInfo": {"cardNumber": "511024198803060014", "cardType": 0,
                                                            "userName": "陈相林"}}
                yield Request(url=self.bind_url, callback=self.bind_parse, method="POST", headers=header,
                              body=json.dumps(bind_data), dont_filter=True, meta={"header": header})
        except Exception:
            pass

    def unbind_parse(self, response, **kwargs):
        try:
            stop_flag = kwargs.get("stop_flag", False)
            if not stop_flag:
                data = json.loads(response.text)
                new_token = data.get("data", {}).get("newToken", "")
                # bind_data = {"authType": 1,
                #              "realNameAuthenticationInfo": {"cardNumber": "511321198612302823", "cardType": 0,
                #                                             "userName": "杜璐"}}
                bind_data = {"authType": 1,
                             "realNameAuthenticationInfo": {"cardNumber": "511024198803060014", "cardType": 0,
                                                            "userName": "陈相林"}}
                header = response.meta.get("header", {})
                header.update({"token": new_token})
                yield Request(url=self.bind_url, callback=self.bind_parse, method="POST", headers=header,
                              body=json.dumps(bind_data), dont_filter=True, cb_kwargs=kwargs, meta={"header": header})
        except Exception:
            pass

    def bind_parse(self, response, **kwargs):
        try:
            data = json.loads(response.text)
            new_token = data.get("data", {}).get("newToken", "")
            header = response.meta.get("header", {})
            header.update({"token": new_token})
            header.pop("Content-Type")
            yield Request(url=self.user_url, callback=self.user_parse, headers=header, dont_filter=True, cb_kwargs=kwargs, meta={"header": header})
        except Exception:
            pass

    def user_parse(self, response, **kwargs):
        try:
            data = json.loads(response.text).get("data", "")
            new_card_number = data.get("userInfo", {}).get("cardNumber", "")
            kwargs.update({"new_card_number": new_card_number})

            header = response.meta.get("header", {})
            header.update({"Content-Type": "application/json; charset=UTF-8"})
            score_data = {"offlineScoreType": 2, "pageNo": 1, "pageSize": 100}
            yield Request(url=self.score_url, callback=self.score_parse, method="POST", headers=header,
                          body=json.dumps(score_data), dont_filter=True, cb_kwargs=kwargs, meta={"header": header})
        except Exception:
            pass

    def score_parse(self, response, **kwargs):
        try:
            header = response.meta.get("header", {})
            score_page_flag = response.meta.get("score_page_flag", False)
            data = json.loads(response.text).get("data", {})
            score_list = response.meta.get("score_list", [])
            score_list.extend(data.get("results", []))
            if not score_page_flag:
                total = data.get("totalCount", 0)
                page_list = []
                if total > 100:
                    page_count = math.ceil(total / 100)
                    page_list = list(range(2, page_count + 1))
            else:
                page_list = response.meta.get("page_list", [])
            if page_list:
                page = page_list.pop(0)
                score_data = {"offlineScoreType": 2, "pageNo": page, "pageSize": 100}
                yield Request(url=self.score_url, callback=self.score_parse, method="POST", headers=header,
                              body=json.dumps(score_data), dont_filter=True, cb_kwargs=kwargs,
                              meta={"score_page_flag": True, "score_list": score_list, "header": header,
                                    "page_list": page_list})
            else:
                kwargs.update({"score_data": score_list})
                race_data = {"nodeLevel": 1, "pageNo": 1, "pageQueryFlag": True, "pageSize": 1000, "parentCode": 10}
                yield Request(url=self.race_url, callback=self.race_parse, method="POST", headers=header,
                              body=json.dumps(race_data), dont_filter=True, cb_kwargs=kwargs, meta={"header": header})
        except Exception:
            pass

    def race_parse(self, response, **kwargs):
        try:
            page_flag = response.meta.get("page_flag", False)
            header = response.meta.get("header", {})
            data = json.loads(response.text)

            race_data_list = response.meta.get("race_data_list", []) if page_flag else []
            race_list = data.get("data", {}).get("results", [])
            for race in race_list:
                race_data_list.append({"赛事名称": race.get("raceInfoResDTO", {}).get("raceName"),
                                  "赛事编号": race.get("raceInfoResDTO", {}).get("raceCode", "")})
            if not page_flag:
                total = data.get("data", {}).get("totalCount", 0)
                page_list = []
                if total > 1000:
                    page_count = math.ceil(total / 1000)
                    page_list = list(range(2, page_count + 1))
            else:
                page_list = response.meta.get("page_list", [])
            if page_list:
                page = page_list.pop(0)
                race_data = {"nodeLevel": 1, "pageNo": page, "pageQueryFlag": True, "pageSize": 1000,
                             "parentCode": 10}
                yield Request(url=self.race_url, callback=self.race_parse, method="POST", headers=header,
                              body=json.dumps(race_data), dont_filter=True, cb_kwargs=kwargs,
                              meta={"header": header, "page_list": page_list, "race_data_list": race_data_list, "page_flag": True})
            else:
                kwargs.update({"race_data": race_data_list})
                header.pop("Content-Type")
                yield Request(url=self.img_url, callback=self.img_parse, headers=header, dont_filter=True, cb_kwargs=kwargs, meta={"header": header})
        except Exception:
            pass

    def img_parse(self, response, **kwargs):
        try:
            header = response.meta.get("header", {})
            img_id = json.loads(response.text).get("data", "")
            kwargs.update({"img_id": img_id})
            yzm_url = self.yzm_url.format(img_id)
            yield Request(url=yzm_url, callback=self.yzm_parse, headers=header, dont_filter=True, cb_kwargs=kwargs, meta={"header": header})
        except Exception:
            pass

    def yzm_parse(self, response, **kwargs):
        try:
            token = kwargs.get("token", "")
            img_id = kwargs.get("img_id", "")
            new_card_number = kwargs.get("new_card_number", "")
            ocr = ddddocr.DdddOcr(beta=True)
            yzm = ocr.classification(response.body)
            register_data = {"raceId": "1000223047", "imageUniqueId": img_id, "cardNumber": new_card_number,
                             "imageVerifyCode": yzm}
            header = response.meta.get("header", {})
            header.update({"Content-Type": "application/json; charset=UTF-8"})
            yield Request(url=self.register_url, callback=self.register_parse, method="POST", headers=header,
                          body=json.dumps(register_data), dont_filter=True, cb_kwargs=kwargs, meta={"header": header})
        except Exception:
            self.logger.info(traceback.format_exc())

    def register_parse(self, response, **kwargs):
        try:
            header = response.meta.get("header", {})
            score_data = kwargs.get("score_data", "")
            register_data = json.loads(response.text).get("data", "")
            kwargs.update({"register_data": register_data})
            score_id_list = [score.get("id", "") for score in score_data]
            if score_id_list:
                score_id = score_id_list.pop(0)
                yield Request(self.certificate_url.format(score_id), callback=self.certificate_parse, headers=header,
                              dont_filter=True, cb_kwargs=kwargs, meta={"header": header, "score_id_list": score_id_list})

        except Exception:
            pass

    def certificate_parse(self, response, **kwargs):
        try:
            header = response.meta.get("header", {})
            certificate_data = response.meta.get("certificate_data", [])
            data = json.loads(response.text).get("data", "")
            certificate_data.append(data)
            score_id_list = response.meta.get("score_id_list", [])
            if score_id_list:
                score_id = score_id_list.pop(0)
                yield Request(self.certificate_url.format(score_id), callback=self.certificate_parse, headers=header,
                              dont_filter=True, cb_kwargs=kwargs,
                              meta={"header": header, "score_id_list": score_id_list, "certificate_data": certificate_data})
            else:
                score_data = kwargs.get("score_data", "")
                race_data = kwargs.get("race_data", "")
                register_data = kwargs.get("register_data", "")
                new_card_number = kwargs.get("new_card_number", "")
                kwargs.update({"stop_flag": True})
                result = {"成绩": score_data, "赛事信息": race_data, "报名信息": register_data, "等级信息": certificate_data}
                yield Request(url=self.unbind_url, callback=self.unbind_parse, method="POST", headers=header,
                              body=json.dumps({"cardNumber": new_card_number}), dont_filter=True, cb_kwargs=kwargs)
        except Exception:
            pass

    def all_race_parse(self, response, **kwargs):
        try:
            header = response.meta.get("header", {})
            page_flag = response.meta.get("page_flag", False)
            all_race_list = response.meta.get("all_race_list", []) if page_flag else []
            all_race = json.loads(response.text).get("data", {}).get("race", {})
            result_list = all_race.get("results", [])
            for data in result_list:
                race_id = data.get("raceId", "")
                race_name = data.get("raceName", "")
                if "内部测试" not in race_name:
                    all_race_list.append(race_id)

            if not page_flag:
                page_list = []
                total = all_race.get("totalCount", 0)
                if total > 1000:
                    page_count = math.ceil(total / 1000)
                    page_list = list(range(2, page_count + 1))
            else:
                page_list = response.meta.get("page_list", [])
            if page_list:
                page = page_list.pop(0)
                data = {"raceCategoryCodeList": ["race_type_offline"], "searchType": "1", "pageNo": str(page),
                        "pageSize": "1000",
                        "keyword": ""}
                yield Request(url=self.all_race_url, callback=self.all_race_parse, method="POST", headers=header,
                              body=json.dumps(data), dont_filter=True, meta={"header": header,
                                                                             "all_race_list": all_race_list,
                                                                             "page_flag": True, "page_list": page_list})
            else:
                score_data = kwargs.get("score_data", "")
                race_data = kwargs.get("race_data", "")
                token = kwargs.get("token", "")
                new_card_number = kwargs.get("new_card_number", "")
                data = json.loads(response.text).get("data", "")
                kwargs.update({"stop_flag": True})
                result = {"成绩": score_data, "赛事信息": race_data, "报名信息": data}
                yield Request(url=self.unbind_url, callback=self.unbind_parse, method="POST", headers=header,
                              body=json.dumps({"cardNumber": new_card_number}), dont_filter=True, cb_kwargs=kwargs)
        except Exception:
            pass


if __name__ == '__main__':
    cmdline.execute("scrapy crawl shuzixindong".split())
